package org.cc.media.player;


import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.cc.media.utils.concurrent.Scheduler;
import org.cc.media.vo.shoutcast.ShoutcastStation;

public class CCGuiPlayer extends JFrame implements ActionListener, ListSelectionListener {
	
	private static final long serialVersionUID = 1419891650474939513L;
	
	public static final String API_KEY = "sh19qvGfsOJkQ0pv";
	
	private ShoutcastApiClient api = new ShoutcastApiClient();

	private CCStreamPlayer player;
	
	private ShoutcastPlaylistDigester digester = new ShoutcastPlaylistDigester();
	
	private static JLabel trackTitle;
	
	private static JLabel albumArt;
	
	private static JButton buyLink;
	
	private Scheduler scheduler = new Scheduler();
	
	private List<ShoutcastStation> stations = new ArrayList<ShoutcastStation>();
	
	public static final void main(String[] args)  {
		CCGuiPlayer player = new CCGuiPlayer();
		player.setSize(800, 600);
		player.setLocation(400, 300);
		try {
			player.init();
			player.setVisible(true);
			player.setDefaultCloseOperation(EXIT_ON_CLOSE);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	
	private void init() throws IOException  {
	    this.getContentPane().setLayout(new FlowLayout());

	    trackTitle = new JLabel("");
	    this.add(trackTitle);
		
		JButton playButton = new JButton("Play!");
		playButton.addActionListener(this);
		this.add(playButton);
		
		JButton stopButton = new JButton("Stop!");
		stopButton.addActionListener(this);
		this.add(stopButton);
		
		stations.addAll(api.getStations("alternative"));
		JList<Object> list = new JList<Object>((Object[]) stations.toArray()); //data has type Object[]
		list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		list.setLayoutOrientation(JList.VERTICAL);
		list.setVisibleRowCount(-1);
		list.addListSelectionListener(this);

		JScrollPane listScroller = new JScrollPane(list);
		listScroller.setPreferredSize(new Dimension(600, 300));

		JTabbedPane tabbed = new JTabbedPane();
		tabbed.setName("Genres");
		tabbed.addTab("Alternative", listScroller);
		this.add(tabbed);
		
		albumArt = new JLabel();
		BufferedImage myPicture = ImageIO.read(this.getClass().getResource("/desert.jpg"));
		Image scaled = myPicture.getScaledInstance(200, -1, Image.SCALE_SMOOTH);
		albumArt.setIcon(new ImageIcon(scaled));
		this.add(albumArt);
		
	    buyLink = new JButton();
		buyLink.addActionListener(this);
		buyLink.setVisible(false);
		this.add(buyLink);
		

	}

	@Override
	public void actionPerformed(ActionEvent event) {
        String action = event.getActionCommand();
        System.out.println("Command: " + action);
        if (action.equals("Play!")) {
            System.out.println("Play Button pressed!");
            startPlayer();
        }
        else if (action.equals("Stop!")) {
            System.out.println("Stop Button pressed!");
            stopPlayer();
        }
        else if (action.equals("Buy this item!")) {
        	try {
        		System.out.println("New Customer!");
        		JButton button = (JButton) event.getSource();
				openWebpage(new URL(button.getName()));
			} catch (MalformedURLException e) {
				showErrorPopup(ExceptionUtils.getStackTrace(e));
			}
        }
    }

	@Override
	public void valueChanged(ListSelectionEvent event) {
		if (!event.getValueIsAdjusting()) {
			String id = stations.get(event.getLastIndex()).getId();
			System.out.println("Going for station: " + stations.get(event.getLastIndex()).getName());
			String url = digester.getUrlFromId(id);
			AudioInputStream stream = getAudioStream(digester.getStreamFromUrl(url));
			SourceDataLine line = getAudioLine(stream);
			if (player == null) {
				player = new CCStreamPlayer(stream, line);
				scheduler.schedule(player);
			} else {
				player.pause();
				player.setStream(stream);
				player.setLine(line);
				player.play();
			}
		}
	}

	private void startPlayer() {
		if (player == null) {
			ShoutcastStation station = (ShoutcastStation) stations.get(0);
			String url = digester.getUrlFromId(station.getId());
			AudioInputStream stream = getAudioStream(digester.getStreamFromUrl(url));
			SourceDataLine line = getAudioLine(stream);
			player = new CCStreamPlayer(stream, line);
			scheduler.schedule(player);
		} else {
			player.play();
		}

	}
	
	private void stopPlayer() {
		player.pause();
	}
	
	private AudioInputStream getAudioStream(InputStream inStream) {
		AudioInputStream audioStream = null;
		try {
			audioStream = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, AudioSystem.getAudioInputStream(inStream));
		} catch (UnsupportedAudioFileException e) {
			e.printStackTrace();
		} catch (IOException e) {
			showErrorPopup(ExceptionUtils.getStackTrace(e));
		}
		return audioStream;
	}
	
	private SourceDataLine getAudioLine(AudioInputStream audioStream) {
		AudioFormat format = audioStream.getFormat();
		DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
		SourceDataLine line = null;
		try {
			line = (SourceDataLine) AudioSystem.getLine(info);
			line.open(format);
			line.start();
		} catch (LineUnavailableException e) {
			showErrorPopup(e.getMessage());
		}
		return line;
	}
	
	
	private void openWebpage(URI uri) {
	    Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
	    if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
	        try {
	            desktop.browse(uri);
	        } catch (Exception e) {
	        	showErrorPopup(ExceptionUtils.getStackTrace(e));
	        }
	    }
	}

	private void openWebpage(URL url) {
	    try {
	        openWebpage(url.toURI());
	    } catch (URISyntaxException e) {
	        showErrorPopup(ExceptionUtils.getStackTrace(e));
	    }
	}
	
	private void showErrorPopup(String message) {
        Window parentWindow = SwingUtilities.windowForComponent(this);
        JDialog dialog = new JDialog(parentWindow);
        dialog.setLocationRelativeTo(this);
        dialog.setSize(500, 400);
        dialog.setModal(true);
        dialog.setTitle("Error");
        JLabel text = new JLabel();
        text.setText("<html><pre>" + message + "</pre></html>");
        JScrollPane pane = new JScrollPane(text);
        dialog.add(pane);
        dialog.setVisible(true);
	}
	
	public static JLabel getTrackTitle() {
		return trackTitle;
	}

	public static JLabel getAlbumArt() {
		return albumArt;
	}

	public static JButton getBuyLink() {
		return buyLink;
	}

}
